Next: Loop Facility, Previous: Blocks and Exits, Up: Control Structure [Contents][Index]
The macros described here provide more sophisticated, high-level looping constructs to complement Emacs Lisp’s basic loop forms (see Iteration in GNU Emacs Lisp Reference Manual).
This package supports both the simple, old-style meaning
of loop and the extremely powerful and flexible
feature known as the Loop Facility or Loop
Macro. This more advanced facility is discussed in the
following section; see Loop Facility. The
simple form of loop is described here.
If cl-loop is followed by zero or more Lisp
expressions, then (cl-loop
exprs…) simply creates an infinite
loop executing the expressions over and over. The loop is
enclosed in an implicit nil block. Thus,
(cl-loop (foo) (if (no-more) (return 72)) (bar))
is exactly equivalent to
(cl-block nil (while t (foo) (if (no-more) (return 72)) (bar)))
If any of the expressions are plain symbols, the loop is instead interpreted as a Loop Macro specification as described later. (This is not a restriction in practice, since a plain symbol in the above notation would simply access and throw away the value of a variable.)
This macro creates a general iterative loop. Each spec is of the form
(var [init [step]])
The loop works as follows: First, each var is
bound to the associated init value as if by a
let form. Then, in each iteration of the loop,
the end-test is evaluated; if true, the loop is
finished. Otherwise, the body forms are evaluated,
then each var is set to the associated
step expression (as if by a cl-psetq
form) and the next iteration begins. Once the
end-test becomes true, the result forms
are evaluated (with the vars still bound to their
values) to produce the result returned by
cl-do.
The entire cl-do loop is enclosed in an
implicit nil block, so that you can use
(cl-return) to break out of the loop at any
time.
If there are no result forms, the loop returns
nil. If a given var has no
step form, it is bound to its init
value but not otherwise modified during the
cl-do loop (unless the code explicitly modifies
it); this case is just a shorthand for putting a (let
((var init)) …) around
the loop. If init is also omitted it defaults to
nil, and in this case a plain
‘var’ can be used in
place of ‘(var)’, again
following the analogy with let.
This example (from Steele) illustrates a loop that applies
the function f to successive pairs of values
from the lists foo and bar; it is
equivalent to the call (cl-mapcar 'f foo bar).
Note that this loop has no body forms at all,
performing all its work as side effects of the rest of the
loop.
(cl-do ((x foo (cdr x))
(y bar (cdr y))
(z nil (cons (f (car x) (car y)) z)))
((or (null x) (null y))
(nreverse z)))
This is to cl-do what let* is to
let. In particular, the initial values are bound
as if by let* rather than let, and
the steps are assigned as if by setq rather than
cl-psetq.
Here is another way to write the above loop:
(cl-do* ((xp foo (cdr xp))
(yp bar (cdr yp))
(x (car xp) (car xp))
(y (car yp) (car yp))
z)
((or (null xp) (null yp))
(nreverse z))
(push (f x y) z))
This is exactly like the standard Emacs Lisp macro
dolist, but surrounds the loop with an implicit
nil block.
This is exactly like the standard Emacs Lisp macro
dotimes, but surrounds the loop with an implicit
nil block. The body is executed with
var bound to the integers from zero (inclusive) to
count (exclusive), in turn. Then the
result form is evaluated with var
bound to the total number of iterations that were done (i.e.,
(max 0 count)) to get the return
value for the loop form.
This loop iterates over all interned symbols. If
obarray is specified and is not nil,
it loops over all symbols in that obarray. For each symbol,
the body forms are evaluated with var
bound to that symbol. The symbols are visited in an
unspecified order. Afterward the result form, if
any, is evaluated (with var bound to
nil) to get the return value. The loop is
surrounded by an implicit nil block.
This is identical to cl-do-symbols except
that the obarray argument is omitted; it always
iterates over the default obarray.
See Mapping over Sequences, for some more functions for iterating over vectors or lists.
Next: Loop Facility, Previous: Blocks and Exits, Up: Control Structure [Contents][Index]